import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { SkillUpgradeThresholdEntity } from "../entities/skill-upgrade-threshold.entity";
import {
  CharacterSkillEntity,
  SkillType,
  SkillSide,
} from "../entities/character-skill.entity";

@Injectable()
export class CharacterSkillService {
  constructor(
    @InjectRepository(CharacterSkillEntity)
    private characterSkillRepository: Repository<CharacterSkillEntity>,
    @InjectRepository(SkillUpgradeThresholdEntity)
    private readonly skillThresholdRepo: Repository<SkillUpgradeThresholdEntity>
  ) {}

  getRequiredProficiencyForUpgrade(
    skillName: string,
    currentGrade: number
  ): number {
    const nextGrade = currentGrade + 1;
    if (nextGrade < 2 || nextGrade > 5) return Number.MAX_SAFE_INTEGER;
    // 优先从阈值表查询
    // 精确使用技能名称与目标等级
    // 如未配置，走兜底表
    // 注意：skillName 需与基础表名称一致
    // 这里使用同步返回，外层调用在ws handler中
    // 实际查询
    // WARNING: 此方法为同步返回数值，调用方应避免频繁调用导致多次IO；
    // 如需缓存，可在服务内增加内存缓存。
    // 由于该方法只读取一次，简单直接查询。
    const row = this.skillThresholdRepo.findOne({
      where: { skillName, nextGrade },
    }) as unknown as { requiredProficiency?: number } | null;
    // 注意：由于本方法为同步，直接访问 Promise 不可行；
    // 因此调用方应优先调用异步版本。为兼容当前调用，我们提供兜底。
    // 兜底通用表
    const fallback: Record<number, number> = {
      2: 200,
      3: 500,
      4: 2000,
      5: 10000,
    };
    // 如果未来改为异步，请将 ws-handlers 中调用改为 await 异步函数
    // 这里先返回兜底值，真实判定在异步版本中完成
    return (
      (row as any)?.requiredProficiency ??
      fallback[nextGrade] ??
      Number.MAX_SAFE_INTEGER
    );
  }

  /**
   * 异步版本：查询数据库阈值
   */
  async getRequiredProficiencyForUpgradeAsync(
    skillName: string,
    currentGrade: number
  ): Promise<number> {
    const nextGrade = currentGrade + 1;
    if (nextGrade < 2 || nextGrade > 5) return Number.MAX_SAFE_INTEGER;
    const row = await this.skillThresholdRepo.findOne({
      where: { skillName, nextGrade },
    });
    if (row && typeof row.requiredProficiency === "number") {
      return row.requiredProficiency;
    }
    const fallback: Record<number, number> = {
      2: 200,
      3: 500,
      4: 2000,
      5: 10000,
    };
    return fallback[nextGrade] ?? Number.MAX_SAFE_INTEGER;
  }

  /**
   * 获取角色的所有技能
   */
  async getCharacterSkills(
    characterId: number
  ): Promise<CharacterSkillEntity[]> {
    try {
      const skills = await this.characterSkillRepository.find({
        where: { characterId },
        order: { skillId: "ASC" },
      });

      // 如果没有技能记录，创建默认技能
      if (skills.length === 0) {
        return await this.createDefaultSkills(characterId);
      }

      return skills;
    } catch (error) {
      console.error("获取角色技能失败:", error);
      throw error;
    }
  }

  /**
   * 根据技能类型获取角色技能
   */
  async getCharacterSkillsByType(
    characterId: number,
    skillType: SkillType
  ): Promise<CharacterSkillEntity[]> {
    try {
      return await this.characterSkillRepository.find({
        where: { characterId, skillType },
        order: { skillId: "ASC" },
      });
    } catch (error) {
      console.error("根据类型获取角色技能失败:", error);
      throw error;
    }
  }

  /**
   * 创建默认技能（基于角色职业类型）
   */
  private async createDefaultSkills(
    characterId: number
  ): Promise<CharacterSkillEntity[]> {
    try {
      // 获取角色信息来确定职业类型
      const character = await this.characterSkillRepository.manager
        .getRepository("characters")
        .findOne({ where: { id: characterId } });

      if (!character) {
        throw new Error("角色不存在");
      }

      const roleType = character.roleType;
      const now = new Date();

      // 根据职业类型创建默认技能
      let defaultSkills: Partial<CharacterSkillEntity>[] = [];

      switch (roleType) {
        case 1: // 武士
          defaultSkills = [
            {
              characterId,
              skillId: 1,
              skillType: SkillType.WARRIOR,
              skillName: "舍身取义",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "舍",
              skillAni: "she-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 9,
              skillType: SkillType.WARRIOR,
              skillName: "劈头盖脸",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "劈",
              skillAni: "pi-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 15,
              skillType: SkillType.WARRIOR,
              skillName: "坚如磐石",
              skillSide: SkillSide.DEFENSIVE,
              skillShort: "固",
              skillAni: "gu-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
          ];
          break;

        case 2: // 文人
          defaultSkills = [
            {
              characterId,
              skillId: 5,
              skillType: SkillType.SCHOLAR,
              skillName: "围点打援",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "围",
              skillAni: "wei-6",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 11,
              skillType: SkillType.SCHOLAR,
              skillName: "乱作一团",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "乱",
              skillAni: "luan-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 18,
              skillType: SkillType.SCHOLAR,
              skillName: "隐姓埋名",
              skillSide: SkillSide.DEFENSIVE,
              skillShort: "暗",
              skillAni: "yin-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
          ];
          break;

        case 3: // 异师
          defaultSkills = [
            {
              characterId,
              skillId: 8,
              skillType: SkillType.MAGE,
              skillName: "煽风点火",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "火",
              skillAni: "huo-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 13,
              skillType: SkillType.MAGE,
              skillName: "天打雷劈",
              skillSide: SkillSide.OFFENSIVE,
              skillShort: "雷",
              skillAni: "lei-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
            {
              characterId,
              skillId: 16,
              skillType: SkillType.MAGE,
              skillName: "金蝉脱壳",
              skillSide: SkillSide.DEFENSIVE,
              skillShort: "脱",
              skillAni: "tuo-8",
              status: 1,
              obtainedAt: now,
              created_at: now,
              updated_at: now,
            },
          ];
          break;

        default:
          throw new Error("无效的职业类型");
      }

      // 保存默认技能
      const savedSkills = await this.characterSkillRepository.save(
        defaultSkills
      );
      return savedSkills;
    } catch (error) {
      console.error("创建默认技能失败:", error);
      throw error;
    }
  }

  /**
   * 学习新技能
   */
  async learnSkill(
    characterId: number,
    skillData: Partial<CharacterSkillEntity>
  ): Promise<CharacterSkillEntity> {
    try {
      const now = new Date();
      const skill = this.characterSkillRepository.create({
        ...skillData,
        characterId,
        obtainedAt: now,
        created_at: now,
        updated_at: now,
      });

      return await this.characterSkillRepository.save(skill);
    } catch (error) {
      console.error("学习技能失败:", error);
      throw error;
    }
  }

  /**
   * 升级技能
   */
  async upgradeSkill(characterId: number, skillId: number): Promise<boolean> {
    try {
      const result = await this.characterSkillRepository.update(
        { characterId, skillId },
        {
          grade: () => "grade + 1",
          updated_at: new Date(),
        }
      );

      return (result.affected || 0) > 0;
    } catch (error) {
      console.error("升级技能失败:", error);
      throw error;
    }
  }

  /**
   * 为角色技能增加熟练度
   */
  async addSkillProficiency(
    characterId: number,
    skillId: number,
    delta: number
  ): Promise<boolean> {
    const inc = Math.max(0, Number(delta || 0));
    if (inc <= 0) return false;
    const result = await this.characterSkillRepository.update(
      { characterId, skillId },
      { useCount: () => `useCount + ${inc}`, updated_at: new Date() }
    );
    return (result.affected || 0) > 0;
  }

  /**
   * 获取单个角色技能
   */
  async getCharacterSkill(
    characterId: number,
    skillId: number
  ): Promise<CharacterSkillEntity | null> {
    const row = await this.characterSkillRepository.findOne({
      where: { characterId, skillId },
    });
    return row || null;
  }

  /**
   * 增加技能使用次数
   */
  async increaseSkillUseCount(
    characterId: number,
    skillId: number
  ): Promise<boolean> {
    try {
      const result = await this.characterSkillRepository.update(
        { characterId, skillId },
        {
          useCount: () => "useCount + 1",
          updated_at: new Date(),
        }
      );

      return (result.affected || 0) > 0;
    } catch (error) {
      console.error("增加技能使用次数失败:", error);
      throw error;
    }
  }

  /**
   * 删除技能
   */
  async deleteSkill(characterId: number, skillId: number): Promise<boolean> {
    try {
      const result = await this.characterSkillRepository.delete({
        characterId,
        skillId,
      });
      return (result.affected || 0) > 0;
    } catch (error) {
      console.error("删除技能失败:", error);
      throw error;
    }
  }
}
